package com.why.jvm.hotspot.src.share.vm.classfile;

import com.why.jvm.hotspot.src.share.tools.DataTranslate;
import com.why.jvm.hotspot.src.share.tools.Stream;
import com.why.jvm.hotspot.src.share.vm.oops.*;
import com.why.jvm.hotspot.src.share.vm.oops.constants.*;
import lombok.extern.slf4j.Slf4j;

/**
 * @author xiaoTian
 * @date 2022/7/16 14:57
 * @Description:
 * 解析字节码：
 * ClassFile{
 *     u4               magic;
 *     u2               minor_version;
 *     u2               major_version;
 *     u2               constant_pool_count;
 *     cp_info          constant_pool[constant_pool_count-1];
 *     u2               access_flags;
 *     u2               this_class;
 *     u2               super_class;
 *     u2               interface_count;
 *     u2               interfaces[interface_count];
 *     u2               fields_count;
 *     field_info       fields[fields_count];
 *     u2               methods_count;
 *     method_info      methods[methods_count];
 *     u2               attributes_count;
 *     attribute_info   attributes[attributes_count];
 * }
 *
 */
@Slf4j
public class ClassFileParser {


    public static InstanceKlass parseClassFile(byte[] content) throws Exception {
        int index = 0;
        InstanceKlass instanceKlass = new InstanceKlass();
        // 魔数
        byte[] magic = new byte[4];
        Stream.readU4Simple(content, index, magic);
        index += 4;
        log.info(DataTranslate.bytesToHexFun1(magic));
        instanceKlass.setMagic(DataTranslate.bytesToHexFun1(magic));

        // minor_version
        byte[] minorVersion = new byte[2];
        Stream.readU2Simple(content, index, minorVersion);
        index += 2;
        instanceKlass.setMinorVersion(DataTranslate.byteToUnsignedShort(minorVersion));

        // major_version
        byte[] majorVersion = new byte[2];
        Stream.readU2Simple(content, index, majorVersion);
        index += 2;
        int majorVersionI = DataTranslate.byteToUnsignedShort(majorVersion);
        instanceKlass.setMajorVersion(majorVersionI);
        log.info("majorVersion:" + majorVersionI);

        // constantPool
        index = parseConstantPool(instanceKlass, content, index);

        byte[] accessFlag = new byte[2];
        Stream.readU2Simple(content, index, accessFlag);
        instanceKlass.setAccessFlag(DataTranslate.byteToUnsignedShort(accessFlag));
        index += 2;
        log.info("accessFlag:" + instanceKlass.getAccessFlag());

        byte[] thisClass = new byte[2];
        Stream.readU2Simple(content, index, thisClass);
        instanceKlass.setThisClass(DataTranslate.byteToUnsignedShort(thisClass));
        index += 2;
        log.info("thisClass:" + instanceKlass.getThisClass());

        byte[] superClass = new byte[2];
        Stream.readU2Simple(content, index, superClass);
        instanceKlass.setSuperClass(DataTranslate.byteToUnsignedShort(superClass));
        index += 2;
        log.info("superClass:" + instanceKlass.getSuperClass());

        index = parseInterface(instanceKlass, content, index);

        index = parseField(instanceKlass, content, index);

        index = parseMethod(instanceKlass, content, index);

        //
        byte[] attributeCount = new byte[2];
        Stream.readU2Simple(content, index, attributeCount);
        index += 2;
        instanceKlass.setAttributeCount(DataTranslate.byteToUnsignedShort(attributeCount));
        parseSourceFile(instanceKlass, content, index);
        return instanceKlass;
    }


    private static int parseInterface(InstanceKlass instanceKlass, byte[] content, int index) {
        byte[] count = new byte[2];
        Stream.readU2Simple(content, index, count);
        index += 2;
        instanceKlass.setInterfaceCount(DataTranslate.byteToUnsignedShort(count));
        log.info("interfaceCount:" + instanceKlass.getInterfaceCount());
        for (int i = 0; i < instanceKlass.getInterfaceCount(); i++) {
            byte[] u2 = new byte[2];
            Stream.readU2Simple(content, index, u2);
            index += 2;
            int nameIndex = DataTranslate.byteToUnsignedShort(u2);
            InterfaceInfo interfaceInfo = new InterfaceInfo();
            interfaceInfo.setConstantPool(instanceKlass.getConstantPool());
            interfaceInfo.setNameIndex(nameIndex);
            instanceKlass.getInterfaceInfos().add(interfaceInfo);
            log.info("interface,getNameIndex:" + interfaceInfo.getNameIndex());
        }
        return index;
    }


    private static int parseField(InstanceKlass instanceKlass, byte[] content, int index) {
        byte[] count = new byte[2];
        Stream.readU2Simple(content, index, count);
        index += 2;
        instanceKlass.setFieldCount(DataTranslate.byteToUnsignedShort(count));
        for (int i = 0; i < instanceKlass.getFieldCount(); i++) {
            FieldInfo fieldInfo = new FieldInfo();
            fieldInfo.setConstantPool(instanceKlass.getConstantPool());
            byte[] u2 = new byte[2];
            Stream.readU2Simple(content, index, u2);
            index += 2;
            fieldInfo.setAccessFlags(DataTranslate.byteToUnsignedShort(u2));
            Stream.readU2Simple(content, index, u2);
            index += 2;
            fieldInfo.setNameIndex(DataTranslate.byteToUnsignedShort(u2));
            Stream.readU2Simple(content, index, u2);
            index += 2;
            fieldInfo.setDescriptorIndex(DataTranslate.byteToUnsignedShort(u2));
            Stream.readU2Simple(content, index, u2);
            index += 2;
            // 解析attribute
            fieldInfo.setAttributesCount(DataTranslate.byteToUnsignedShort(u2));
            log.info(fieldInfo.toString());
            if (fieldInfo.getAttributesCount() > 0) {
                throw new RuntimeException("字段属性尚未开发解析！");
            }
//            for (int j = 0; j < fieldInfo.getAttributesCount(); j++) {
//                index = parseAttribute(instanceKlass,content,index);
//            }
            instanceKlass.getFieldInfos().add(fieldInfo);
        }
        return index;
    }


    private static int parseSourceFile(InstanceKlass instanceKlass, byte[] content, int index) {
        SourceFileAttribute sourceFileAttribute = new SourceFileAttribute();
        byte[] u2 = new byte[2];
        Stream.readU2Simple(content, index, u2);
        index += 2;
        sourceFileAttribute.setAttributeNameIndex(DataTranslate.byteToUnsignedShort(u2));

        byte[] u4 = new byte[4];
        Stream.readU4Simple(content, index, u4);
        index += 4;
        int attributeLength = DataTranslate.byteArrayToInt(u4);
        sourceFileAttribute.setAttributeLength(attributeLength);

        Stream.readU2Simple(content, index, u2);
        index += 2;
        sourceFileAttribute.setSourceFileIndex(DataTranslate.byteToUnsignedShort(u2));
        sourceFileAttribute.setConstantPool(instanceKlass.getConstantPool());
        instanceKlass.getAttributeInfos().add(sourceFileAttribute);
        return index;
    }

    private static int parseCodeAttribute(CodeAttribute codeAttribute, byte[] content, int index) {
        byte[] u2 = new byte[2];
        Stream.readU2Simple(content, index, u2);
        index += 2;
        int attributeNameIndex = DataTranslate.byteToUnsignedShort(u2);


        byte[] u4 = new byte[4];
        Stream.readU4Simple(content, index, u4);
        index += 4;
        int attributeLength = DataTranslate.byteArrayToInt(u4);

        Stream.readU2Simple(content, index, u2);
        index += 2;
        int maxStack = DataTranslate.byteToUnsignedShort(u2);


        Stream.readU2Simple(content, index, u2);
        index += 2;
        int maxLocals = DataTranslate.byteToUnsignedShort(u2);

        Stream.readU4Simple(content, index, u4);
        index += 4;
        int codeLength = DataTranslate.byteArrayToInt(u4);

        byte[] code = new byte[codeLength];
        Stream.readSimple(content, index, codeLength, code);
        index += codeLength;

        Stream.readU2Simple(content, index, u2);
        index += 2;
        int exceptionTableLength = DataTranslate.byteToUnsignedShort(u2);

        Stream.readU2Simple(content, index, u2);
        index += 2;

        int attributesCount = DataTranslate.byteToUnsignedShort(u2);

        codeAttribute.setAttributeNameIndex(attributeNameIndex);
        codeAttribute.setAttributeLength(attributeLength);
        codeAttribute.setMaxStack(maxStack);
        codeAttribute.setMaxLocals(maxLocals);
        codeAttribute.setCodeLength(codeLength);
        codeAttribute.setCode(code);
        codeAttribute.setExceptionTableLength(exceptionTableLength);
        codeAttribute.setAttributesCount(attributesCount);
        if (attributesCount == 2) {
            // LineNumberTable
            index = parseLineNumberTable(content, codeAttribute, index);

            // LocalVariableTable
            index = parseLocalVariableTable(content, codeAttribute, index);
        } else {
            // LineNumberTable
            index = parseLineNumberTable(content, codeAttribute, index);
        }
        return index;
    }


    private static int parseLineNumberTable(byte[] content, CodeAttribute codeAttribute, int index) {
        byte[] u2 = new byte[2];
        byte[] u4 = new byte[4];
        LineNumberTableAttribute attribute = new LineNumberTableAttribute();
        attribute.setConstantPool(codeAttribute.getConstantPool());

        Stream.readU2Simple(content, index, u2);
        index += 2;
        int attributeNameIndex = DataTranslate.byteToUnsignedShort(u2);

        Stream.readU4Simple(content, index, u4);
        index += 4;
        int attributeLength = DataTranslate.byteArrayToInt(u4);

        Stream.readU2Simple(content, index, u2);
        index += 2;
        int lineNumberTableLength = DataTranslate.byteToUnsignedShort(u2);


        // 遍历
        for (int i = 0; i < lineNumberTableLength; i++) {
            LineNumberTable table = new LineNumberTable();
            Stream.readU2Simple(content, index, u2);
            index += 2;
            int startPc = DataTranslate.byteToUnsignedShort(u2);

            Stream.readU2Simple(content, index, u2);
            index += 2;
            int lineNumber = DataTranslate.byteToUnsignedShort(u2);
            table.setLineNumber(lineNumber);
            table.setStartPc(startPc);
            attribute.getLineNumberTableList().add(table);
        }


        attribute.setAttributeNameIndex(attributeNameIndex);
        attribute.setAttributeLength(attributeLength);
        attribute.setLineNumberTableLength(lineNumberTableLength);

        codeAttribute.getAttributeInfos().add(attribute);

        return index;
    }

    private static int parseLocalVariableTable(byte[] content, CodeAttribute codeAttribute, int index) {

        LocalVariableTableAttribute localVariableTableAttribute = new LocalVariableTableAttribute();
        LocalVariableTable table = new LocalVariableTable();
        localVariableTableAttribute.setConstantPool(codeAttribute.getConstantPool());
        table.setConstantPool(codeAttribute.getConstantPool());
        localVariableTableAttribute.getTables().add(table);

        byte[] u2 = new byte[2];
        byte[] u4 = new byte[4];
        Stream.readU2Simple(content, index, u2);
        index += 2;
        int attributeNameIndex = DataTranslate.byteToUnsignedShort(u2);

        Stream.readU4Simple(content, index, u4);
        index += 4;
        int attributeLength = DataTranslate.byteArrayToInt(u4);

        Stream.readU2Simple(content, index, u2);
        index += 2;
        int tableLength = DataTranslate.byteToUnsignedShort(u2);

        Stream.readU2Simple(content, index, u2);
        index += 2;
        int starPc = DataTranslate.byteToUnsignedShort(u2);

        Stream.readU2Simple(content, index, u2);
        index += 2;
        int length = DataTranslate.byteToUnsignedShort(u2);

        Stream.readU2Simple(content, index, u2);
        index += 2;
        int nameIndex = DataTranslate.byteToUnsignedShort(u2);

        Stream.readU2Simple(content, index, u2);
        index += 2;
        int descriptor = DataTranslate.byteToUnsignedShort(u2);

        Stream.readU2Simple(content, index, u2);
        index += 2;
        int tableIndex = DataTranslate.byteToUnsignedShort(u2);

        localVariableTableAttribute.setLocalVariableTableLength(tableLength);
        localVariableTableAttribute.setAttributeNameIndex(attributeNameIndex);
        localVariableTableAttribute.setAttributeLength(attributeLength);

        table.setIndex(tableIndex);
        table.setStartPc(starPc);
        table.setLength(length);
        table.setNameIndex(nameIndex);
        table.setDescriptorIndex(descriptor);
        codeAttribute.getAttributeInfos().add(localVariableTableAttribute);
        return index;
    }


    private static int parseMethod(InstanceKlass instanceKlass, byte[] content, int index) {
        byte[] count = new byte[2];
        Stream.readU2Simple(content, index, count);
        index += 2;
        instanceKlass.setMethodCount(DataTranslate.byteToUnsignedShort(count));

        for (int i = 0; i < instanceKlass.getMethodCount(); i++) {
            byte[] u2 = new byte[2];
            MethodInfo methodInfo = new MethodInfo();
            methodInfo.setConstantPool(instanceKlass.getConstantPool());
            instanceKlass.getMethodInfos().add(methodInfo);
            Stream.readU2Simple(content, index, u2);
            index += 2;
            methodInfo.setAccessFlags(DataTranslate.byteToUnsignedShort(u2));

            Stream.readU2Simple(content, index, u2);
            index += 2;
            methodInfo.setNameIndex(DataTranslate.byteToUnsignedShort(u2));

            Stream.readU2Simple(content, index, u2);
            index += 2;
            methodInfo.setDescriptorIndex(DataTranslate.byteToUnsignedShort(u2));

            Stream.readU2Simple(content, index, u2);
            index += 2;
            methodInfo.setAttributesCount(DataTranslate.byteToUnsignedShort(u2));

            for (int j = 0; j < methodInfo.getAttributesCount(); j++) {
                CodeAttribute codeAttribute = new CodeAttribute();
                codeAttribute.setConstantPool(instanceKlass.getConstantPool());
                index = parseCodeAttribute(codeAttribute, content, index);
                instanceKlass.getMethodInfos().get(i).getAttributeInfos().add(codeAttribute);
            }
        }
        return index;
    }

    private static int parseConstantPool(InstanceKlass instanceKlass, byte[] content, int index) throws Exception {

        ConstantPool constantPool = new ConstantPool();
        instanceKlass.setConstantPool(constantPool);

        byte[] count = new byte[2];
        Stream.readU2(content, index, count);
        index += 2;
        constantPool.setCount(DataTranslate.byteToUnsignedShort(count));
        constantPool.initConstantPool();

        log.info("constantPoolCount:" + instanceKlass.getConstantPool().getCount());
        byte[] u2 = new byte[2];
        byte[] u4 = new byte[4];
        byte[] u8 = new byte[8];
        for (int i = 1; i < constantPool.getCount(); i++) {
            int tag = Stream.readU1Simple(content, index);
            index += 1;
            switch (tag) {
                case ConstantPool.CONSTANT_Class: {
                    constantPool.getTag()[i] = tag;
                    Stream.readU2Simple(content, index, u2);
                    index += 2;
                    int nameIndex = DataTranslate.byteToUnsignedShort(u2);

                    ConstantClass constantClass = new ConstantClass();
                    constantClass.setNameIndex(nameIndex);
                    constantClass.setTag(tag);
                    constantClass.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantClass);
                    log.info("[" + (i + 1) + "]" + "nameAndTypeIndex:" + nameIndex);
                    break;
                }
                case ConstantPool.CONSTANT_Methodref: {
                    ConstantMethodrefInfo constantMethodrefInfo = new ConstantMethodrefInfo();
                    constantPool.getTag()[i] = tag;
                    Stream.readU2Simple(content, index, u2);
                    index += 2;

                    int classIndex = DataTranslate.byteToUnsignedShort(u2);

                    log.info("[" + (i) + "]" + "classIndex:" + DataTranslate.byteToUnsignedShort(u2));

                    Stream.readU2Simple(content, index, u2);
                    int nameAndTypeIndex = DataTranslate.byteToUnsignedShort(u2);
                    index += 2;
                    constantMethodrefInfo.setTag(tag);
                    constantMethodrefInfo.setClassIndex(classIndex);
                    constantMethodrefInfo.setNameAndTypeIndex(nameAndTypeIndex);
                    constantMethodrefInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantMethodrefInfo);
                    log.info("[" + (i) + "]" + "nameAndTypeIndex:" + DataTranslate.byteToUnsignedShort(u2));
                    break;
                }
                case ConstantPool.CONSTANT_Fieldref: {
                    ConstantFieldrefInfo constantFieldrefInfo = new ConstantFieldrefInfo();
                    constantPool.getTag()[i] = tag;
                    Stream.readU2Simple(content, index, u2);
                    index += 2;
                    int classIndex = DataTranslate.byteToUnsignedShort(u2);
                    log.info("[" + (i) + "]" + "classIndex:" + DataTranslate.byteToUnsignedShort(u2));

                    Stream.readU2Simple(content, index, u2);
                    int nameAndTypeIndex = DataTranslate.byteToUnsignedShort(u2);
                    index += 2;

                    constantFieldrefInfo.setTag(tag);
                    constantFieldrefInfo.setClassIndex(classIndex);
                    constantFieldrefInfo.setNameAndTypeIndex(nameAndTypeIndex);
                    constantFieldrefInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantFieldrefInfo);
                    log.info("[" + (i) + "]" + "nameAndTypeIndex:" + DataTranslate.byteToUnsignedShort(u2));
                    break;
                }
                case ConstantPool.CONSTANT_InterfaceMethodref: {
                    constantPool.getTag()[i] = tag;
                    Stream.readU2Simple(content, index, u2);
                    index += 2;
                    int classIndex = DataTranslate.byteToUnsignedShort(u2);
                    log.info("[" + (i) + "]" + "classIndex:" + DataTranslate.byteToUnsignedShort(u2));

                    Stream.readU2Simple(content, index, u2);
                    index += 2;
                    int nameAndTypeIndex = DataTranslate.byteToUnsignedShort(u2);
                    ConstantInterfaceMethodrefInfo constantInterfaceMethodrefInfo = new ConstantInterfaceMethodrefInfo();
                    constantInterfaceMethodrefInfo.setTag(tag);
                    constantInterfaceMethodrefInfo.setClassIndex(classIndex);
                    constantInterfaceMethodrefInfo.setNameAndTypeIndex(nameAndTypeIndex);
                    constantInterfaceMethodrefInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantInterfaceMethodrefInfo);
                    log.info("[" + (i) + "]" + "nameAndTypeIndex:" + DataTranslate.byteToUnsignedShort(u2));
                    break;
                }
                case ConstantPool.CONSTANT_String: {
                    constantPool.getTag()[i] = tag;
                    Stream.readU2Simple(content, index, u2);
                    index += 2;

                    ConstantStringInfo constantStringInfo = new ConstantStringInfo();
                    int stringIndex = DataTranslate.byteToUnsignedShort(u2);

                    constantStringInfo.setStringIndex(stringIndex);
                    constantStringInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantStringInfo);
                    log.info("[" + (i) + "]" + "CONSTANT_String:" + DataTranslate.byteToUnsignedShort(u2));
                    break;
                }
                case ConstantPool.CONSTANT_Integer: {
                    constantPool.getTag()[i] = tag;
                    Stream.readU4Simple(content, index, u4);
                    index += 4;
                    int value = DataTranslate.byteArrayToInt(u4);
                    ConstantIntegerInfo constantIntegerInfo = new ConstantIntegerInfo();

                    constantIntegerInfo.setValue(value);
                    constantIntegerInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantIntegerInfo);
                    log.info("[" + (i) + "]" + "CONSTANT_Integer:" + DataTranslate.byteArrayToInt(u4));
                    break;
                }
                case ConstantPool.CONSTANT_Float: {
                    ConstantFloatInfo constantFloatInfo = new ConstantFloatInfo();
                    constantPool.getTag()[i] = tag;
                    Stream.readU4Simple(content, index, u4);
                    index += 4;

                    float value = DataTranslate.byteToFloat(u4);
                    constantFloatInfo.setValue(value);
                    constantFloatInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantFloatInfo);
                    log.info("[" + (i) + "]" + "nameAndTypeIndex:" + DataTranslate.byteToFloat(u4));
                    break;
                }
                case ConstantPool.CONSTANT_Long: {
                    constantPool.getTag()[i] = tag;
                    Stream.readU8Simple(content, index, u8);
                    index += 8;
                    long value = DataTranslate.bytes2long(u8);

                    ConstantLongInfo constantLongInfo = new ConstantLongInfo();
                    constantLongInfo.setValue(value);
                    constantLongInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantLongInfo);
                    log.info("[" + (i) + "]" + "CONSTANT_Long:" + DataTranslate.bytes2long(u8));
                    break;
                }
                case ConstantPool.CONSTANT_Double: {
                    constantPool.getTag()[i] = tag;

                    Stream.readU8Simple(content, index, u8);
                    index += 8;

                    double value = DataTranslate.bytesToDouble(u8, true);

                    ConstantDoubleInfo constantDoubleInfo = new ConstantDoubleInfo();
                    constantDoubleInfo.setValue(value);
                    constantDoubleInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantDoubleInfo);
                    log.info("[" + (i) + "]" + "CONSTANT_Double:" + DataTranslate.bytesToDouble(u8, true));
                    break;
                }
                case ConstantPool.CONSTANT_NameAndType: {
                    constantPool.getTag()[i] = tag;

                    Stream.readU2Simple(content, index, u2);
                    int nameIndex = DataTranslate.byteToUnsignedShort(u2);
                    index += 2;
                    log.info("[" + (i) + "]" + "nameIndex:" + DataTranslate.byteToUnsignedShort(u2));


                    Stream.readU2Simple(content, index, u2);
                    index += 2;
                    int descriptorIndex = DataTranslate.byteToUnsignedShort(u2);

                    ConstantNameAndTypeInfo nameAndTypeInfo = new ConstantNameAndTypeInfo();
                    nameAndTypeInfo.setTag(tag);
                    nameAndTypeInfo.setNameIndex(nameIndex);
                    nameAndTypeInfo.setDescriptorIndex(descriptorIndex);
                    nameAndTypeInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, nameAndTypeInfo);
                    log.info("[" + (i) + "]" + "descriptorIndex:" + DataTranslate.byteToUnsignedShort(u2));
                    break;
                }
                case ConstantPool.CONSTANT_Utf8: {
                    constantPool.getTag()[i] = tag;
                    Stream.readU2Simple(content, index, u2);
                    int len = DataTranslate.byteToUnsignedShort(u2);
                    index += 2;
                    log.info("[" + (i) + "]" + "length:" + len);

                    byte[] bytes = new byte[len];
                    Stream.readSimple(content, index, len, bytes);
                    index += len;

                    ConstantUtf8Info utf8Info = new ConstantUtf8Info();
                    utf8Info.setTag(tag);
                    utf8Info.setLength(len);
                    utf8Info.setValue(new String(bytes));
                    utf8Info.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, utf8Info);
                    log.info("[" + (i) + "]" + "bytes:" + new String(bytes));
                    break;
                }
                case ConstantPool.CONSTANT_MethodHandle: {
                    constantPool.getTag()[i] = tag;
                    byte referenceKind = Stream.readU1Simple(content, index);
                    index++;
                    log.info("[" + (i) + "]" + "referenceKind:" + referenceKind);
                    Stream.readU2Simple(content, index, u2);
                    int referenceIndex = DataTranslate.byteToUnsignedShort(u2);
                    index += 2;

                    ConstantMethodHandleInfo constantMethodrefInfo = new ConstantMethodHandleInfo();
                    constantMethodrefInfo.setTag(tag);
                    constantMethodrefInfo.setReferenceKind(referenceKind);
                    constantMethodrefInfo.setReferenceIndex(referenceIndex);
                    constantMethodrefInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantMethodrefInfo);
                    log.info("[" + (i) + "]" + "descriptorIndex:" + DataTranslate.byteToUnsignedShort(u2));
                    break;
                }
                case ConstantPool.CONSTANT_MethodType: {
                    constantPool.getTag()[i] = tag;

                    Stream.readU2Simple(content, index, u2);
                    int descriptorIndex = DataTranslate.byteToUnsignedShort(u2);
                    index += 2;

                    ConstantMethodTypeInfo constantMethodTypeInfo = new ConstantMethodTypeInfo();
                    constantMethodTypeInfo.setTag(tag);
                    constantMethodTypeInfo.setDescriptorIndex(descriptorIndex);
                    constantMethodTypeInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantMethodTypeInfo);
                    log.info("[" + (i) + "]" + "descriptorIndex:" + DataTranslate.byteToUnsignedShort(u2));
                    break;
                }
                case ConstantPool.CONSTANT_InvokeDynamic: {
                    constantPool.getTag()[i] = tag;

                    Stream.readU2Simple(content, index, u2);
                    index += 2;
                    int bootstrapMethodAttrIndex = DataTranslate.byteToUnsignedShort(u2);
                    log.info("[" + (i) + "]" + "bootstrapMethodAttrIndex:" + DataTranslate.byteToUnsignedShort(u2));

                    Stream.readU2Simple(content, index, u2);
                    int nameAndTypeIndex = DataTranslate.byteToUnsignedShort(u2);
                    index += 2;

                    ConstantInvokeDynamicInfo constantInvokeDynamicInfo = new ConstantInvokeDynamicInfo();
                    constantInvokeDynamicInfo.setTag(tag);
                    constantInvokeDynamicInfo.setBootstrapMethodAttrIndex(bootstrapMethodAttrIndex);
                    constantInvokeDynamicInfo.setNameAndTypeIndex(nameAndTypeIndex);
                    constantInvokeDynamicInfo.setConstantPool(constantPool);
                    constantPool.getConstantPoolMap().put(i, constantInvokeDynamicInfo);
                    log.info("[" + (i) + "]" + "nameAndTypeIndex:" + DataTranslate.byteToUnsignedShort(u2));
                    break;
                }
            }
        }
        return index;
    }




}
